package com.yikome.tracker.htc;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Value;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.yikome.utils.JSONUtils;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.DES;
import cn.hutool.http.HttpRequest;

public class HCTLogisticsUtils {
	
	private static String iv = "AZCGKUYC" ;
	
	private static String v = "DB7B243E87F06A06A12AA6596936B539" ; 
	
	private static String batchLogisticsTrackUrl = "https://www.hct.com.tw/phone/searchGoods_Main_Xml.ashx" ;
	
	@Value("${logistics.hctTracker.iv}")
	public void setIv(String iv) {
		HCTLogisticsUtils.iv = iv;
	}
	@Value("${logistics.hctTracker.v}")
	public void setV(String v) {
		HCTLogisticsUtils.v = v;
	}
	@Value("${logistics.hctTracker.batchLogisticsTrackUrl}")
	public void setBatchLogisticsTrackUrl(String batchLogisticsTrackUrl) {
		HCTLogisticsUtils.batchLogisticsTrackUrl = batchLogisticsTrackUrl;
	}

	private static DES createDES() {
		
		String keyStr = LocalDate.now(ZoneId.of("+8")).plusDays(8).format(DateTimeFormatter.ofPattern("yyyyMMdd"));
		
		DES des = new DES(Mode.CBC, Padding.PKCS5Padding, keyStr.getBytes(), iv.getBytes());
		
		return des ;
	}
	
	private static String encodeNo(String logisticCode) {
		
		return createDES().encryptBase64(logisticCode, CharsetUtil.CHARSET_UTF_8);
	}
	
	private static String decodeMsg(String msg) {
		
		return createDES().decryptStr(msg, CharsetUtil.CHARSET_UTF_8);
	}
	
	private static String getLogisticTrack(List<String> logisticCodes) {

		StringBuilder sourceNoStr = new StringBuilder("<?xml version=\"1.0\" encoding=\"utf-8\"?><qrylist>");
		for (String logisticCode : logisticCodes) {
			sourceNoStr.append(StrUtil.format("<order orderid=\"{}\"></order>", logisticCode));
		}
		sourceNoStr.append("</qrylist>");
		
		String requestUrl = StrUtil.format("{batchLogisticsTrackUrl}?no={no}&v={v}", ImmutableMap.of( "batchLogisticsTrackUrl", batchLogisticsTrackUrl, "no", encodeNo(sourceNoStr.toString()), "v", v)) ; 
		
		String response = HttpRequest.get(requestUrl).execute().body();
		
		String decodeMsg = decodeMsg(response);
		
		return decodeMsg ; 
	}
	
	public static List<HCTLogisticsResponse> getHCTLogisticsDTO(List<String> logisticCodes) {
		
		List<HCTLogisticsResponse> result = new ArrayList<>();
		
		String decodeMsg = getLogisticTrack(logisticCodes);
		
		Document document = XmlUtil.parseXml(decodeMsg);
		
		List<Element> ordersElements = XmlUtil.getElements(document.getDocumentElement(), "orders");
		
		for (Element ordersElement : ordersElements) {
			
			String ordersid = ordersElement.getAttribute("ordersid");
			
			List<HCTLogisticsDetailsResponse> logisticsDetails = new ArrayList<>();
			
			List<Element> orderElements = XmlUtil.getElements(ordersElement, "order");
			
			for (Element orderElement : orderElements) {
				
				String wrktime = orderElement.getAttribute("wrktime");
				String status = orderElement.getAttribute("status");
				
				HCTLogisticsDetailsResponse detailsDTO = HCTLogisticsDetailsResponse.builder()
						.wrktime(wrktime)
						.event(status)
						.build();
				
				logisticsDetails.add(detailsDTO);
			}
			
			HCTLogisticsResponse hctLogisticsDTO = HCTLogisticsResponse.builder()
					.ordersid(ordersid)
					.logisticsDetails(logisticsDetails)
					.build();
			
			result.add(hctLogisticsDTO);
		}
		
		return result ; 
	}
	
	
	public static void main(String[] args) throws Exception {
		
		List<HCTLogisticsResponse> hctLogisticsDTO = getHCTLogisticsDTO(ImmutableList.of("6718226911", "6709328065"));
		
		System.out.println(JSONUtils.toJsonString(hctLogisticsDTO));
	}
}
